#include "list.h"
//#include "def.h"

#define NULL    ((void *)0)

#define _MEM_END	0x33f00000
#define _MEM_START	0x300f0000
#define MAX_ORDER 11

/* 根据伙伴分配内存开始-结束地址计算总共的页面数*/
#define KERNEL_PAGE_NUM	((KERNEL_PAGING_END-KERNEL_PAGING_START)/MEM_PAGE_SIZE)
/*the start and end of the page structure should be storaged in.*/
#define KERNEL_PAGE_END	_MEM_END
/* 所有的页框保存在内存的后端 */
#define KERNEL_PAGE_START	(KERNEL_PAGE_END - KERNEL_PAGE_NUM*sizeof(struct page))

#define MAX_ORDER_PAGE_NUM	(1<<(MAX_ORDER-1))	//分配4M的内存空间
#define SPLIT_HALF(x,order)	((x)+(1<<(order)))	//当前buddy块页框折半开始位置

#define BUDDY_END(x,order)	((x)+(1<<(order))-1)	//当前buddy块页框结束位置
#define NEXT_BUDDY_START(x,order)	((x)+(1<<(order)))	//下一个buddy块页框起始位置
#define PREV_BUDDY_START(x,order)	((x)-(1<<(order)))	//前一个buddy块页框起始位置

/*page flags*/
#define PAGE_AVAILABLE		0x00
#define PAGE_DIRTY			0x01
#define PAGE_PROTECT		0x02
#define PAGE_BUDDY_BUSY		0x04
#define PAGE_IN_CACHE		0x08


#define MEM_PAGE_SHIFT	(12)
#define MEM_PAGE_SIZE	(1<<MEM_PAGE_SHIFT)
#define MEM_PAGE_MASK	(~(MEM_PAGE_SIZE-1))

#define KERNEL_MEM_END	(_MEM_END)
/*the bigin and end of the kernel mem which is needed to be paged.*/
#define KERNEL_PAGING_START	((_MEM_START+(~MEM_PAGE_MASK))&((MEM_PAGE_MASK)))
#define	KERNEL_PAGING_END	(((KERNEL_MEM_END-KERNEL_PAGING_START)/(MEM_PAGE_SIZE+sizeof(struct page)))*(MEM_PAGE_SIZE)+KERNEL_PAGING_START)


#define MAX_BUDDY_PAGE_NUM	(11)	//
#define AVERAGE_PAGE_NUM_PER_BUDDY	(KERNEL_PAGE_NUM/MAX_BUDDY_PAGE_NUM)
#define PAGE_NUM_FOR_EACH_BUDDY(j) ((AVERAGE_PAGE_NUM_PER_BUDDY>>(j))*(1<<(j)))
#define PAGE_NUM_FOR_MAX_BUDDY	((1<<MAX_BUDDY_PAGE_NUM)-1)	//25:11001限定用户最多可以分配1M的内存空间

#define KMEM_CACHE_DEFAULT_ORDER	(0)
#define KMEM_CACHE_MAX_ORDER		(5)
#define KMEM_CACHE_SAVE_RATE		(0x5a)
#define KMEM_CACHE_PERCENT			(0x64)
#define KMEM_CACHE_MAX_WAST			(MEM_PAGE_SIZE-KMEM_CACHE_SAVE_RATE*MEM_PAGE_SIZE/KMEM_CACHE_PERCENT)

#define KMALLOC_BIAS_SHIFT			(5)				//32byte minimal
#define KMALLOC_MAX_SIZE			(4096)
#define KMALLOC_MINIMAL_SIZE_BIAS	(1<<(KMALLOC_BIAS_SHIFT))
#define KMALLOC_CACHE_SIZE			(KMALLOC_MAX_SIZE/KMALLOC_MINIMAL_SIZE_BIAS)
#define kmalloc_cache_size_to_index(size)	((((size))>>(KMALLOC_BIAS_SHIFT)))

void init_page_map(void);
struct page *alloc_pages(unsigned long flag,int order);
void free_pages(struct page *pg,int order);
void *get_free_pages(unsigned long flag,int order);
void put_free_pages(void *addr,int order);

int kmalloc_init(void);
void *kmalloc(unsigned long size);
void kfree(void *addr);
void *get_pt_pages(void);

